package com.ecar.cos.controller;

import com.ecar.common.cipher.MD5;
import com.ecar.common.util.FileTool;
import com.ecar.common.util.PropertyUtil;
import com.ecar.common.util.SpringContextUtil;
import com.ecar.common.util.StringUtil;
import net.sf.json.JSONObject;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * Created by 30 on 2016/7/26.
 * Copyed by fire on 2017/11/15
 * @noinspection unused
 */
@Controller
@RequestMapping(value = "/up", method = RequestMethod.POST)
public class UploadController {

	private static final Logger log = LoggerFactory.getLogger(UploadController.class);

	private static final long UPLOAD_SIZE_LIMIT = 5242880;        // 1024 * 1024 * 5 = 5MB
	private String host;
	private String dir;

	public UploadController() {
		this.host = null;
		this.dir = null;
	}

	@ResponseBody
	@RequestMapping(value = "/img")
	public JSONObject uploadImg(@RequestParam("file") CommonsMultipartFile file,
								HttpServletRequest request,
								HttpServletResponse response) {
		String attributeName = request.getParameter("attributeName");
		if (!check(attributeName)) return err();
		if (file.getSize() > UPLOAD_SIZE_LIMIT) return over(5);

		String uri = uri(request);
		String originName = file.getOriginalFilename();
		String ext = "";
		if (originName.lastIndexOf(".") > 0) ext = originName.substring(originName.lastIndexOf("."));
		String filename = new MD5().getMD5ofStr(String.valueOf(originName.hashCode()));
		filename = System.currentTimeMillis() + "_" + filename.toUpperCase() + ext;
		String filepath = filepath(uri, filename);
		String path = dir + uri;

		if (FileTool.writeFile(filename, path, file))
			return ok(filepath, file.getOriginalFilename(), attributeName, file.getSize());

		return fail();
	}

	@ResponseBody
	@RequestMapping(value = "/apk")
	public JSONObject uploadApk(@RequestParam("file") CommonsMultipartFile file,
								HttpServletRequest request,
								HttpServletResponse response) {
		String attributeName = request.getParameter("attributeName");
		if (!check(attributeName)) return err();
		if (file.getSize() > (UPLOAD_SIZE_LIMIT * 100)) return over(500);

		String originName = file.getOriginalFilename();
		String ext = "";
		if (originName.lastIndexOf(".") > 0) ext = originName.substring(originName.lastIndexOf("."));
		String filename = new MD5().getMD5ofStr(String.valueOf(originName.hashCode()));
		filename = System.currentTimeMillis() + "_" + filename.toUpperCase() + ext;
		if (!filename.endsWith(".apk")) {
			JSONObject ret = new JSONObject();
			ret.put("code", 403);
			ret.put("message", "上传文件格式错误，请上传文件名后缀为apk的文件包！");
			return ret;
		}

		String uri = uri(request);
		String filepath = filepath(uri, filename);
		String path = dir + uri;
		String fixed = dir + request.getContextPath() + "/f/apk/" + attributeName + ".apk";

		if (FileTool.writeFile(filename, path, file)) {
			try {
				FileUtils.copyFile(new File(path + "/" + filename), new File(fixed));
				return ok(filepath, file.getOriginalFilename(), attributeName, file.getSize());
			} catch (IOException e) { e.printStackTrace(); }
		}
		return fail();
	}

	@ResponseBody
	@RequestMapping(value = "/avatar/b64")
	public JSONObject uploadAvatar(HttpServletRequest request, HttpServletResponse response, @RequestBody String base64) {
		String attributeName = request.getParameter("attributeName");
		if (!check(attributeName)) return err();

		String uri = uri(request);
		String filename = filename("jpg");
		String filepath = filepath(uri, filename);
		String path = dir + uri;

		log.debug("upload file uri: " + uri);
		if (FileTool.base64ToImageFile(filename, path, base64))
			return ok(filepath, filename, attributeName);
		return fail();
	}

	@ResponseBody
	@RequestMapping(value = "/code")
	public JSONObject uploadCode(HttpServletRequest request, HttpServletResponse response) {
		String attributeName = request.getParameter("attributeName");
		String code = request.getParameter("code");
		if (!check(attributeName) || StringUtil.isEmpty(code)) return err();

		String uri = uri(request);
		String filename = filename(code, "jpg");
		String filepath = filepath(uri, filename);
		String path = dir + uri;

		log.debug("upload file uri: " + uri);
		boolean ok = false;
		if ("qr".equalsIgnoreCase(attributeName)) {
			String text = request.getParameter("text");
			if (StringUtil.isEmpty(text)) {
				ok = FileTool.generateQrCode(filename, path, code);
			} else {
				ok = FileTool.generateQrCode(filename, path, code, text);
			}
		} else if ("bar".equalsIgnoreCase(attributeName)) {
			ok = FileTool.generateBarcode128(filename, path, code);
		}
		if (ok) return ok(filepath, filename, attributeName);
		return fail();
	}

	@ResponseBody
	@RequestMapping(value = "/code/batch")
	public JSONObject uploadCodes(HttpServletRequest request, HttpServletResponse response) {
		String attributeName = request.getParameter("attributeName");
		String codeAll = request.getParameter("code");
		if (!check(attributeName) || StringUtil.isEmpty(codeAll)) return err();

		List<JSONObject> result = new ArrayList<>();
		String uri = uri(request);
		String path = dir + uri;
		String[] codes = codeAll.split(",");
		log.debug("upload file uri: " + uri);
		for (String code : codes) {
			boolean ok = false;
			String filename = filename(code, "jpg");
			String filepath = filepath(uri, filename);
			if ("qr".equalsIgnoreCase(attributeName)) {
				ok = FileTool.generateQrCode(filename, path, code);
			} else if ("bar".equalsIgnoreCase(attributeName)) {
				ok = FileTool.generateBarcode128(filename, path, code);
			}
			if (ok)  {
				JSONObject codeJson = new JSONObject();
				codeJson.put("filePath", filepath);
				codeJson.put("name", filename);
				codeJson.put("code", code);
				result.add(codeJson);
			}
		}
		if (result.size() > 0) return ok(result, attributeName);
		return fail();
	}

	private JSONObject over(int max) {
		JSONObject ret = new JSONObject();
		ret.put("code", 403);
		ret.put("message", "文件过大，请勿上传大小超过" + max + "MB的文件。");
		return ret;
	}

	private JSONObject err() {
		JSONObject ret = new JSONObject();
		ret.put("code", 401);
		ret.put("message", "文件上传参数错误。");
		return ret;
	}

	private JSONObject fail() {
		JSONObject ret = new JSONObject();
		ret.put("code", 500);
		ret.put("result", "上传文件失败。");
		return ret;
	}

	private JSONObject ok(String filepath, String filename, String attributeName) {
		JSONObject ret = new JSONObject();
		ret.put("code", 200);
		ret.put("filePath", filepath);
		ret.put("name", filename);
		ret.put("attributeName", attributeName);
		return ret;
	}

	private JSONObject ok(List<JSONObject> result, String attributeName) {
		JSONObject ret = new JSONObject();
		ret.put("code", 200);
		ret.put("result", result);
		ret.put("attributeName", attributeName);
		return ret;
	}

	private JSONObject ok(String filepath, String filename, String attributeName, long filesize) {
		JSONObject ret = new JSONObject();
		ret.put("code", 200);
		ret.put("filePath", filepath);
		ret.put("name", filename);
		ret.put("size", filesize);
		ret.put("attributeName", attributeName);
		return ret;
	}

	private boolean check(String attributeName) {
		if (this.host == null || this.dir == null) {
			PropertyUtil propertyUtil = (PropertyUtil) SpringContextUtil.getBean("propertyUtil");
			host = propertyUtil.getValue("config.host.url");
			dir = propertyUtil.getValue("config.upload.path");
		}

		return StringUtil.isNotEmpty(attributeName);
	}


	private String uri(HttpServletRequest request) {
		SimpleDateFormat dateformat = new SimpleDateFormat("yyyyMMdd");
		return request.getContextPath() + "/f/" + request.getParameter("attributeName")
			+ "/" + dateformat.format(new Date());
	}

	private String filepath(String uri, String filename) {
		return host + uri + "/" + filename;
	}

	private String filename(String name, String ext) {
		MD5 md5 = new MD5();
		return md5.getMD5ofStr(name) + "." + ext;
	}

	private String filename(String ext) {
		return System.currentTimeMillis() + generateRandom(6) + "." + ext;
	}

	private String generateRandom(int length) {
		length = length < 6 ? 6 : (length > 22 ? 22 : length);
		String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		Random random = new Random();
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < length; i++) {
			int num = random.nextInt(str.length());
			buf.append(str.charAt(num));
		}
		return buf.toString();
	}
}
